package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.pojo.MarketingSettingValuePojo;
import com.xbongbong.paas.service.CouponService;
import com.xbongbong.paas.service.CouponTempleteService;
import com.xbongbong.paas.service.WriteOffRecordService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.message.constant.MarketingManagementPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.DistributorMessageRabbitMqDTO;
import com.xbongbong.pro.rabbitmq.producer.BaseProducer;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.CouponEntity;
import com.xbongbong.saas.domain.entity.MarketingSettingEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.WriteOffRecordEntity;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.enums.MarketingManagementSettingEnum;
import com.xbongbong.saas.enums.WriteOffRecordCouponEnum;
import com.xbongbong.saas.enums.WriteOffRecordEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.OrderEnum;
import com.xbongbong.saas.enums.business.ReturnEnum;
import com.xbongbong.saas.enums.dictionary.AllOutBoundEnum;
import com.xbongbong.saas.enums.dictionary.CouponStatusEnum;
import com.xbongbong.saas.enums.dictionary.WriteOffStatusEnum;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.CouponModel;
import com.xbongbong.saas.model.MarketingSettingModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.WriteOffRecordModel;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service("CouponService")
public class CouponServiceImpl implements CouponService {

    private static final Logger LOG = LoggerFactory.getLogger(CouponServiceImpl.class);

    @Resource
    private CouponModel couponModel;
    @Resource
    private WriteOffRecordService writeOffRecordService;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private CouponTempleteService couponTempleteService;
    @Resource
    private BaseProducer baseProducer;
    @Resource
    private MarketingSettingModel marketingSettingModel;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private WriteOffRecordModel writeOffRecordModel;



    @Override
    public void changeCouponStatus(PaasFormDataEntity newPaasFormDataEntity, Integer code) throws XbbException {
        JSONObject data = newPaasFormDataEntity.getData();
        JSONArray couponArray = data.getJSONArray(OrderEnum.COUPON_ID.getAttr());
        List<CouponEntity> updateList = new ArrayList<>();
        List<Long> couponIdList = new ArrayList<>();
        long now = DateUtil.getInt();
        for (int i = 0; i < couponArray.size(); i++) {
            CouponEntity couponEntity = new CouponEntity();
            couponEntity.setUpdateTime(now);
            couponEntity.setId(couponArray.getLong(i));
            couponEntity.setStatus(CouponStatusEnum.USED.getCode());
            updateList.add(couponEntity);
            couponIdList.add(couponArray.getLong(i));
        }
        if (CollectionUtils.isNotEmpty(updateList)) {
            couponModel.updateBatch(updateList, newPaasFormDataEntity.getCorpid());
        }
        List<CouponEntity> couponEntityList = couponModel.findEntitysByIdIn(couponIdList, newPaasFormDataEntity.getCorpid());
        Runnable runnable = () -> {
            try {
                couponTempleteService.updateUseNum(couponEntityList, newPaasFormDataEntity.getCorpid());
                writeOffRecordService.insertRecord(newPaasFormDataEntity, couponEntityList);
            } catch (Exception e) {
                LOG.error("CouponServiceImpl插入核销记录", e);
            }
            try {
                StringBuilder sb = new StringBuilder();
                for (CouponEntity couponEntity : couponEntityList) {
                    sb.append(couponEntity.getName()).append(",");
                }
                sb.deleteCharAt(sb.length() - 1);
                String time = DateTimeUtil.getDateStringEpochSecond(newPaasFormDataEntity.getAddTime());
                Long orderId = data.getLong(OrderEnum.ORDERER_ID.getAttr());
                PushRefTypePojo.Options options = new PushRefTypePojo.Options(newPaasFormDataEntity.getAppId(), newPaasFormDataEntity.getMenuId(), newPaasFormDataEntity.getFormId(), newPaasFormDataEntity.getId(), Collections.singletonList(newPaasFormDataEntity.getId()), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CONTRACT.getCode(), XbbRefTypeEnum.CONTRACT.getCode());
                DistributorMessageRabbitMqDTO distributorMessageRabbitMqDTO = new DistributorMessageRabbitMqDTO(newPaasFormDataEntity.getCorpid(), Arrays.asList(orderId.toString()), Collections.singletonList(newPaasFormDataEntity.getDataId()), 0,
                        null, I18nMessageUtil.getMessage(MarketingManagementPushConstant.DISTRIBUTOR_COUPON_USE_PUSH_TITLE),String.format(I18nMessageUtil.getMessage(MarketingManagementPushConstant.DISTRIBUTOR_COUPON_USE_PUSH_CONTENT),
                        time, newPaasFormDataEntity.getSerialNo(), sb.toString()) , null, options, DistributorMarkEnum.DISTRIBUTOR.getCode());
                baseProducer.sendMessage(PushTypeEnum.DISTRIBUTOR_COUPON_USE_PUSH, distributorMessageRabbitMqDTO);
            } catch (Exception e) {
                LOG.error("优惠券核销", e);
            }
        };
        threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);

    }

    @Override
    public void returnCoupon(ContractEntityExt contractEntityExt, JSONObject data, String corpid) throws XbbException {


        JSONObject contractData = contractEntityExt.getData();
        JSONArray couponIds = contractData.getJSONArray(OrderEnum.COUPON_ID.getAttr());
        if (CollectionUtils.isEmpty(couponIds)) {
            return;
        }
        //只有整单退货，只有一个出库发货单的情况下
        if (Objects.equals(contractData.getString(ContractEnum.ALL_OUT_BOUND.getAttr()), AllOutBoundEnum.ALL_OUT.getCode())
                && Objects.equals(contractData.getJSONArray(ContractEnum.OUTSTOCK_ID.getAttr()), BasicConstant.ONE)) {
            //判断全部退货
            Long outstockId = contractData.getJSONArray(ContractEnum.OUTSTOCK_ID.getAttr()).getLong(0);

            List<OutstockProductEntity> outstockProductEntities = outstockProductModel.getProductsByOutstockIdIn(corpid, Arrays.asList(outstockId));

            Map<Long, Integer> outstockProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

            outstockProductEntities.forEach(item -> {
                Integer num = outstockProductMap.getOrDefault(item.getProductId(), 0);
                num++;
                outstockProductMap.put(item.getProductId(), num);
            });

            List<ContractProductEntity> contractProductByContractIdIn = contractProductModel.getContractProductByContractIdIn(corpid, Arrays.asList(data.getLongValue(ReturnEnum.RED_CONTRACT_ID.getAttr())));

            Map<Long, Integer> contractProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

            contractProductByContractIdIn.forEach(item -> {
                Integer num = contractProductMap.getOrDefault(item.getProductId(), 0);
                num++;
                contractProductMap.put(item.getProductId(), num);
            });

            for (Map.Entry<Long, Integer> entry : outstockProductMap.entrySet()) {
                Long productId = entry.getKey();
                Integer num = entry.getValue();
                Integer contractNum = contractProductMap.getOrDefault(productId, 0);
                if (!Objects.equals(contractNum, num)) {
                    return;
                }
            }

            MarketingSettingEntity settingType = marketingSettingModel.getByType(MarketingManagementSettingEnum.COUPON_USAGE_SETTING.getCode(), corpid);
            MarketingSettingValuePojo marketingSettingValuePojo = JSONObject.parseObject(settingType.getSettingValue(), MarketingSettingValuePojo.class);
            if (Objects.equals(marketingSettingValuePojo.getBack(), BasicConstant.ONE)) {
                List<CouponEntity> updateList = new ArrayList<>();
                for (int i = 0; i < couponIds.size(); i++) {
                    CouponEntity couponEntity = new CouponEntity();
                    couponEntity.setId(couponIds.getLong(i));
                    couponEntity.setStatus(CouponStatusEnum.RECEIVED.getCode());
                    updateList.add(couponEntity);
                }
                couponModel.updateBatch(updateList, corpid);

                Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                params.put(ParameterConstant.CORPID, corpid);
                params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
                params.put("orderId",  contractEntityExt.getId());
                List<WriteOffRecordEntity> entities = writeOffRecordModel.findEntities(params);
                if (CollectionUtils.isNotEmpty(entities)) {
                    WriteOffRecordEntity writeOffRecordEntity = entities.get(0);
                    JSONObject recordEntityData = writeOffRecordEntity.getData();
                    JSONArray couponArray = recordEntityData.getJSONArray(WriteOffRecordEnum.COUPON.getAttr());
                    for (int i = 0; i < couponArray.size(); i++) {
                        JSONObject coupon = couponArray.getJSONObject(i);
                        coupon.put(WriteOffRecordCouponEnum.STATUS.getAttr(), WriteOffStatusEnum.WRITTEN_OFF.getCode());
                    }
                    writeOffRecordModel.update(writeOffRecordEntity);
                }
            }
        }
    }
}
